package com.yhy.common.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.yhy.common.service.MyJdbcTemplate;
import com.yhy.common.vo.SysBusDaynamicDS;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Spring JDBC 实时数据库访问
 * 
 * @author yanghuiyuan
 * @date 2018-08-25
 * @version 1.0
 */
public class DynamicDBUtil {

	private static Logger LOGGER = LoggerFactory.getLogger(DynamicDBUtil.class);

	/**
	 * 多数据连接池
	 */
	private static Map<String,DruidDataSource> dbSources = new HashMap<String,DruidDataSource>();

	public static Map<String, SysBusDaynamicDS> dynamicDataSourceMap = new HashMap<String, SysBusDaynamicDS>();

	/**
	 * 获取数据源【最底层方法，不要随便调用】
	 * @param dynamicSourceEntity
	 * @return
	 */
	private static DruidDataSource getJdbcDataSource(final SysBusDaynamicDS dynamicSourceEntity) {
		DruidDataSource dataSource = new DruidDataSource();
		
		String driverClassName = dynamicSourceEntity.getDriverClass();
		String url = dynamicSourceEntity.getUrl();
		String dbUser = dynamicSourceEntity.getDbUser();
		String dbPassword = dynamicSourceEntity.getDbPassword();

		dataSource.setDriverClassName(driverClassName);
		dataSource.setDbType(dynamicSourceEntity.getDbType());
		dataSource.setUrl(url);
		dataSource.setUsername(dbUser);
		dataSource.setPassword(dbPassword);
		dataSource.setDefaultAutoCommit(true);
		dataSource.setMaxActive(5);
		dataSource.setMinIdle(1);

		return dataSource;
	}
	
	/**
	 * 通过dbkey,获取数据源
	 * @param dbKey
	 * @return
	 */
	public static DruidDataSource getDbSourceByDbKey(final String dbKey) {
		//获取多数据源配置
		SysBusDaynamicDS dynamicSourceEntity = dynamicDataSourceMap.get(dbKey);
		//先判断缓存中是否存在数据库链接
		DruidDataSource cacheDbSource = dbSources.get(dbKey);
		if(cacheDbSource!=null && cacheDbSource.isEnable()){
			return cacheDbSource;
		}else{
			DruidDataSource dataSource = getJdbcDataSource(dynamicSourceEntity);
			dbSources.put(dbKey, dataSource);
			return dataSource;
		}
	}
	
	/**
	 * 关闭数据库连接池
	 *  @param dbKey
	 * @return 
	 * @return
	 */
	public static void closeDBkey(final String dbKey){
		DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
		try {
			if(dataSource!=null && dataSource.isEnable()){
				dataSource.getConnection().commit();
				dataSource.getConnection().close();
				dataSource.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	
	public static MyJdbcTemplate getJdbcTemplate(String dbKey) {
		DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
		MyJdbcTemplate jdbcTemplate = new MyJdbcTemplate(dataSource);
		return jdbcTemplate;
	}
	
	/**
     * Executes the SQL statement in this <code>PreparedStatement</code> object,
     * which must be an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
     * <code>DELETE</code>; or an SQL statement that returns nothing,
     * such as a DDL statement.
     */
	public static int update(final String dbKey, String sql, Object... param)
	{
		int effectCount = 0;
		JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);

		if (ArrayUtils.isEmpty(param)) {
			effectCount = jdbcTemplate.update(sql);
		} else {
			effectCount = jdbcTemplate.update(sql, param);
		}
		return effectCount;
	}

	public static Map<String, Object> findOne(final String dbKey, String sql, Object... param) {
		List<Map<String, Object>> list;
		list = findList(dbKey, sql, param);

		if(list == null || list.isEmpty())
		{
			LOGGER.error("Except one, but not find actually");
			return null;
		}
		
		if(list.size() > 1)
		{
			LOGGER.error("Except one, but more than one actually");
		}
		
		return list.get(0);
	}

	public static List<Map<String, Object>> findListByHash(final String dbKey, String sql, HashMap<String, Object> data){
		List<Map<String, Object>> list;
		JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
		//根据模板获取sql
		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
		list = namedParameterJdbcTemplate.queryForList(sql, data);
		return list;
	}

	public static Map<String, Object> findOneByHash(final String dbKey, String sql, HashMap<String, Object> data){
		List<Map<String, Object>> list;
		list = findListByHash(dbKey, sql, data);
		if(list == null || list.isEmpty()){
			LOGGER.error("Except one, but not find actually");
			return null;
		}
		if(list.size() > 1){
			LOGGER.error("Except one, but more than one actually");
		}
		return list.get(0);
	}

	public static List<Map<String, Object>> findList(final String dbKey, String sql, Object... param) {
		List<Map<String, Object>> list;
		JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
		
		if (ArrayUtils.isEmpty(param)) {
			list = jdbcTemplate.queryForList(sql);
		} else {
			list = jdbcTemplate.queryForList(sql, param);
		}
		return list;
	}

	public static <T> List<T> findList(final String dbKey, String sql, Class<T> clazz,Object... param) {
		List<T> list;
		JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
		
		if (ArrayUtils.isEmpty(param)) {
			list = jdbcTemplate.queryForList(sql,clazz);
		} else {
			list = jdbcTemplate.queryForList(sql,clazz,param);
		}
		return list;
	}

	
}
